package com.fengwk.support.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;

import com.fengwk.support.exception.BaseException;
import com.fengwk.support.util.LoggerUtils.Logger;

public class ImageUtils {

	private static final Logger LOG = LoggerUtils.getLogger(ImageUtils.class);
	
	private static final Pattern PATTERN_BASE64 = Pattern.compile("^data:image/(.+);base64,");
	
	private ImageUtils() {
		throw new BaseException("can not instance " + getClass());
	}
	
	public static String toBase64(InputStream is, boolean isClose) {
		return toBase64(IoUtils.toBytes(is, isClose));
	}
	
	public static String toBase64(InputStream is) {
		return toBase64(is, false);
	}
	
	public static String toBase64(byte[] bytes) {
		return CodeUtils.base64Encode(bytes);
	}
	
	public static Image fromBase64(String str) {
		if (StringUtils.isBlank(str)) {
			return null;
		}
		str = StringUtils.toDbc(str).trim();
		Matcher matcher = PATTERN_BASE64.matcher(str);
		String imgType = null;
		String imgBase64 = null;
		while (matcher.find()) {
			imgType = matcher.group(1);
			imgBase64 = str.substring(matcher.end());
		}
		if(StringUtils.isBlank(imgType) || StringUtils.isBlank(imgBase64)) {
			return null;
		}
		return new Image(imgType, CodeUtils.base64Decode(imgBase64));
	}
	
	public static BufferedImage cut(BufferedImage img, int x, int y, int width, int height) {
		BufferedImage resImg = new BufferedImage(width, height, img.getType());
		for (int xBuf = x; xBuf < x + width; xBuf ++) {
			for (int yBuf = y; yBuf < y + height; yBuf ++) {
				int rgb = img.getRGB(xBuf, yBuf);
				resImg.setRGB(xBuf - x, yBuf - y, rgb);
			}
		}
		return resImg;
	}

	public static class Image implements Serializable {
		
		private static final long serialVersionUID = -3009646120234836629L;
		
		private String type;
		private byte[] content;
		
		private Image(String type, byte[] content) {
			this.type = type;
			this.content = content;
		}
		
		public BufferedImage getBufferedImage() {
			BufferedImage bi = null;
			try {
				bi = ImageIO.read(IoUtils.toInputStream(content));
			} catch (IOException e) {
			    LOG.error(e);
			}
			return bi;
		}
		
		public void write(String path) {
			if(path.indexOf(".") == -1) {
				path += "." + type;
			}
			write(FileUtils.buildFile(path));
		}
		
		public void write(File file) {
			try {
				ImageIO.write(getBufferedImage(), type, file);
			} catch (IOException e) {
			    LOG.error(e);
			}
		}
		
		public String getType() {
			return type;
		}

		public void setType(String type) {
			this.type = type;
		}

		public byte[] getContent() {
			return content;
		}

		public void setContent(byte[] content) {
			this.content = content;
		}
		
	}

}
